﻿
Imports std
Imports xmlctrl
Imports rssctrl
Imports wfileis.data

Public MustInherit Class apipage
    Inherits cacheControlProcessor

    Private recentTopicCount As Int64 = npos
    Private recentTopicLength As Int64 = npos
    Private Shared timer3Guid As System.Guid = Nothing
    Private Shared pings As list(Of String) = Nothing

    Protected Overrides Function normalRetiredTicks() As Long
        Return secondsToTicks(30)
    End Function

    Public Overrides Sub initial(Optional ByVal config As configParser = Nothing)
        MyBase.initial(config)
        assert(Not config Is Nothing, "apipage needs a valid configuration to initialize.")
        recentTopicCount = config.parameter(configNaming.apipage.name, configNaming.apipage.recentTopicCount, _
                                            configNaming.defaultValue.apipage.recentTopicCount)
        recentTopicLength = config.parameter(configNaming.apipage.name, configNaming.apipage.recentTopicLength, _
                                             configNaming.defaultValue.apipage.recentTopicLength)
        loosenSPMLimit()
    End Sub

    Protected MustOverride Function generateRoot(ByVal context As httpContext) As xmlcontrol
    Protected MustOverride Function processTopic(ByVal context As httpContext, ByVal root As xmlcontrol, _
                                                 ByVal key As String, ByVal record As record, _
                                                 ByVal infos As vector(Of pointer(Of info)), _
                                                 ByVal contentLength As Int64) As Boolean
    Protected MustOverride Sub processFailedTopic(ByVal context As httpContext, ByVal root As xmlcontrol, _
                                                  ByVal key As String)
    Protected MustOverride Sub processNoContent(ByVal context As httpContext, ByVal root As xmlcontrol)
    Protected MustOverride Sub addresponseHeaders(ByVal context As httpContext)

    Private Function generateRoot() As xmlcontrol
        Return generateRoot(httpServer2.currentContext())
    End Function

    Private Function processTopic(ByVal key As String, ByVal record As record, _
                                  ByVal infos As vector(Of pointer(Of info)), ByVal root As Object) As Boolean
        Return processTopic(httpServer2.currentContext(), convertor.cast(Of xmlcontrol)(root), _
                            key, record, infos, recentTopicLength)
    End Function

    Private Sub processFailedTopic(ByVal key As String, ByVal root As Object)
        processFailedTopic(httpServer2.currentContext(), convertor.cast(Of xmlcontrol)(root), key)
    End Sub

    Private Sub processNoContent(ByVal root As Object)
        processNoContent(httpServer2.currentContext(), convertor.cast(Of xmlcontrol)(root))
    End Sub

    Private Shared Sub pingVisitCounter()
        Dim referer As String = Nothing
        SyncLock pings
            If Not pings.empty() Then
                referer = pings.first()
                pings.pop_front()
            End If
        End SyncLock
        If Not isemptystring(referer) Then
            If Not pingHttpWeb(configDelegate.visitCounterLink, timeoutMS:=16000, _
                               userAgent:=Nothing, referer:=referer) Then
                raiseError("cannot ping visit counter link " + configDelegate.visitCounterLink, _
                           errorHandle.errorType.warning)
            End If
        End If
    End Sub

    Protected NotOverridable Overrides Function processImpl(ByVal context As httpContext, _
                                                            ByRef control As xmlcontrol) As Boolean
        SyncLock pings
            pings.push_back(context.url().full())
        End SyncLock
        control = generateRoot(context)
        wfileis.processRecentTopics(0, recentTopicCount, _
                                    AddressOf processTopic, _
                                    AddressOf processFailedTopic, _
                                    AddressOf processNoContent, _
                                    control, Nothing)
        Return True
    End Function

    Shared Sub New()
        pings = New list(Of String)()
        timer3Guid = timer3.addcall(AddressOf pingVisitCounter, 1000)
    End Sub
End Class
